package com.dongdongshop.controller;


import ch.qos.logback.core.encoder.EchoEncoder;
import com.alibaba.dubbo.config.annotation.Reference;
import com.dongdongshop.constant.SmsConstant;
import com.dongdongshop.data.HttpResponseEnum;
import com.dongdongshop.data.Result;
import com.dongdongshop.pojo.user.TbUser;
import com.dongdongshop.service.UserServiceI;
import com.dongdongshop.shiro.ShiroUtils;
import com.dongdongshop.util.HttpClientUtil;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Controller
@RequestMapping("user")
public class UserController {

    private final Logger logger= LoggerFactory.getLogger(UserController.class);

    @Reference
    private UserServiceI userServiceI;
    @Resource
    private RocketMQTemplate rocketMQTemplate;
    @Resource
    private RedisTemplate redisTemplate;

    //跳转登录页面
    @RequestMapping("toLogin")
    public String toLogin(){
        return "login";
    }

    //跳转注册页面
    @RequestMapping("toRegister")
    public String toRegister(){
        return "register";
    }

    @RequestMapping("login")
    public String login(String username, String password, Model model){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token=new UsernamePasswordToken(username,password);
        try {
            subject.login(token);
        }catch (UnknownAccountException u){
            model.addAttribute("message","用户不存在");
            return "login";
        }catch (IncorrectCredentialsException i){
            model.addAttribute("message","密码不正确");
            return "login";
        }
        return "index";
    }

    //发送验证码
    @RequestMapping("sendCode")
    @ResponseBody
    public Result sendCode(String phone){
        try {
           //生成4为随机验证码
            String code = RandomStringUtils.randomNumeric(4);
            //将手机号和验证码发送mq
            String phoneByCode=""+phone+","+code+"";
            rocketMQTemplate.convertAndSend("sms_code",phoneByCode);
            //将code保存到redis中方
            HashOperations hash = redisTemplate.opsForHash();
            hash.put(SmsConstant.PHONECODE,phone,code);
            //设置超时时间
            redisTemplate.expire(SmsConstant.PHONECODE,1, TimeUnit.HOURS);
            logger.info("发送成功");
            return Result.jsonResponse(HttpResponseEnum.OK);
        }catch (Exception e){
            logger.error("系统错愕",e);
            return Result.jsonResponse(HttpResponseEnum.FAIL);
        }
    }

    //注册
    @RequestMapping("insertUser")
    @ResponseBody
    public Result insertUser(TbUser user,String code){
        try {
            if (StringUtils.isBlank(user.getUsername())){
                return Result.jsonResponse(HttpResponseEnum.FAIL).setData("用户名不能为空");
            }
            if (StringUtils.isBlank(user.getPassword())){
                return Result.jsonResponse(HttpResponseEnum.FAIL).setData("密码不能为空");
            }
            if (StringUtils.isBlank(user.getPhone())){
                return Result.jsonResponse(HttpResponseEnum.FAIL).setData("手机号不能为空");
            }
            //从redis中取出code
            String codes =(String) redisTemplate.opsForHash().get(SmsConstant.PHONECODE, user.getPhone());
            if (!code.equals(codes)){
                return Result.jsonResponse(HttpResponseEnum.FAIL).setData("验证码不一致");
            }
            String salt = ShiroUtils.generateSalt(6);
            String md5 = ShiroUtils.encryptPassword("MD5", user.getPassword(), salt, 3);
            user.setSalt(salt);
            user.setPassword(md5);
            user.setCreated(new Date());
            user.setUpdated(new Date());


            //判断用户存在不
            List<TbUser> tbUsers =userServiceI.getUserName(user.getUsername());
            if (tbUsers.size()==1){
                return Result.jsonResponse(HttpResponseEnum.FAIL).setData("用户已存在");
            }
            //增加用户
            int users=userServiceI.insertUser(user);
            if (users>0){
                return Result.jsonResponse(HttpResponseEnum.OK);
            }else {
                return Result.jsonResponse(HttpResponseEnum.FAIL);
            }
        }catch (Exception e){
            logger.error("系统错误", e);
            return  Result.jsonResponse(HttpResponseEnum.FAIL);
        }
    }

    //httpClient发送验证码
    @RequestMapping("sendClient")
    @ResponseBody
    public Result sendClient(String phone){
        try {
            //生成4为随机验证码
            String code = RandomStringUtils.randomNumeric(4);
             //将code保存到redis中方
            HashOperations hash = redisTemplate.opsForHash();
            hash.put(SmsConstant.PHONECODE,phone,code);
            //设置超时时间
            redisTemplate.expire(SmsConstant.PHONECODE,1, TimeUnit.HOURS);
            signMessage(phone,code);
            logger.info("发送成功");
            return Result.jsonResponse(HttpResponseEnum.OK);
        }catch (Exception e){
            logger.error("系统错误", e);
            return  Result.jsonResponse(HttpResponseEnum.FAIL);
        }
    }
    //在阿里云API参考 请求签名里得示例 地址https://help.aliyun.com/document_detail/101343.html?spm=a2c4g.11186623.6.618.1e7d6ed1aYteCw
    public void signMessage(String phoneNum,String code) throws Exception {
        String accessKeyId = "LTAI4GGVDj2itAnhTMPvRc1L";
        String accessSecret = "C8LyU35VquqHEdAUPIQv0xKxtrczoU";
        java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区
        java.util.Map<String, String> paras = new java.util.HashMap<String, String>();
        // 1. 系统参数
        paras.put("SignatureMethod", "HMAC-SHA1");
        paras.put("SignatureNonce", java.util.UUID.randomUUID().toString());
        paras.put("AccessKeyId", accessKeyId);
        paras.put("SignatureVersion", "1.0");
        paras.put("Timestamp", df.format(new java.util.Date()));
        paras.put("Format", "XML");
        // 2. 业务API参数  对应SmsServiceImpl里得信息
        paras.put("Action", "SendSms");
        paras.put("Version", "2017-05-25");
        paras.put("RegionId", "cn-hangzhou");
        paras.put("PhoneNumbers", phoneNum);
        paras.put("SignName", "顺顺通1号");
        paras.put("TemplateParam", "{\"sms_code\":"+code+"}");//
        paras.put("TemplateCode", "SMS_194026835");
//        paras.put("OutId", "123");
        // 3. 去除签名关键字Key
        if (paras.containsKey("Signature"))
            paras.remove("Signature");
        // 4. 参数KEY排序
        java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>();
        sortParas.putAll(paras);
        // 5. 构造待签名的字符串
        java.util.Iterator<String> it = sortParas.keySet().iterator();
        StringBuilder sortQueryStringTmp = new StringBuilder();
        while (it.hasNext()) {
            String key = it.next();
            sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key)));
        }
        String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append("GET").append("&");
        stringToSign.append(specialUrlEncode("/")).append("&");
        stringToSign.append(specialUrlEncode(sortedQueryString));
        String sign = sign(accessSecret + "&", stringToSign.toString());
        // 6. 签名最后也要做特殊URL编码
        String signature = specialUrlEncode(sign);
        System.out.println(paras.get("SignatureNonce"));
        System.out.println("\r\n=========\r\n");
        System.out.println(paras.get("Timestamp"));
        System.out.println("\r\n=========\r\n");
        System.out.println(sortedQueryString);
        System.out.println("\r\n=========\r\n");
        System.out.println(stringToSign.toString());
        System.out.println("\r\n=========\r\n");
        System.out.println(sign);
        System.out.println("\r\n=========\r\n");
        System.out.println(signature);
        System.out.println("\r\n=========\r\n");
        // 最终打印出合法GET请求的URL
        System.out.println("http://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp);
        HttpClientUtil.doGet("http://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp);

    }

    public static String specialUrlEncode(String value) throws Exception {
        return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
    }
    public static String sign(String accessSecret, String stringToSign) throws Exception {
        javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
        mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1"));
        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
        return new sun.misc.BASE64Encoder().encode(signData);
    }


    //忘记密码
    @RequestMapping("forgetPassword")
    public String forgetPassword(){
        return "forgetPassword";
    }

    //像邮箱发送验证码
    @RequestMapping("sendEmail")
    @ResponseBody
    public Result sendEmail(String email){
        try {
            //随机生成四位数
            String code = RandomStringUtils.randomNumeric(4);
            //保存到redis中
            HashOperations hashOperations = redisTemplate.opsForHash();
            hashOperations.put(SmsConstant.EMAILCODE,email,code);
            //超时时间
            redisTemplate.expire(SmsConstant.EMAILCODE,1,TimeUnit.HOURS);
            //发送消息
            userServiceI.sendEmail(email,code);
            return Result.jsonResponse(HttpResponseEnum.OK);
        }catch (Exception e){
            logger.error("系统错误",e);
            return Result.jsonResponse(HttpResponseEnum.FAIL);
        }
    }

    @RequestMapping("submitCode")
    public String submitCode(String email,String code){
        String emailByCode = (String) redisTemplate.opsForHash().get(SmsConstant.EMAILCODE, email);
        if (!code.equals(emailByCode)){
            return "forgetPassword";
        }
        return "resetSuccess";
    }

    @RequestMapping("resetPassword")
    @ResponseBody
    public Result resetPassword(String username,String password){
        try {
            Map<String,String> map = ShiroUtils.getSalt(password);
            String salt = map.get("盐");
            String md5 = map.get("密文");
            userServiceI.resetPassword(username,salt,md5);
            return Result.jsonResponse(HttpResponseEnum.OK);
        }catch (Exception e){
            logger.error("系统错误",e);
            return Result.jsonResponse(HttpResponseEnum.FAIL);
        }
    }
}
